package main

import "fmt"

func main() {
	fmt.Println(isValid("[{}][][]{}({})"))
}

func isValid(s string) bool {
	var mapSymbols = map[rune]byte{')': '(', '}': '{', ']': '['}
	st := newStack()
	for _, v := range s {
		switch v {
		case '(', '{', '[':
			st.push(byte(v))
		default:
			if st.isEmpty() {
				return false
			}
			if tmp := st.pop(); tmp != mapSymbols[v] {
				return false
			}
		}
	}
	if st.isEmpty() {
		return true
	}
	return false
}

type stack struct {
	head *linkedList
	size int
}

type linkedList struct {
	next *linkedList
	val  byte
}

func newStack() *stack {
	return &stack{
		head: &linkedList{},
	}
}

func (st *stack) push(val byte) {
	st.head.next = &linkedList{
		next: st.head.next,
		val:  val,
	}
	st.size++
}

func (st *stack) pop() byte {
	tmp := st.head.next
	st.head.next = st.head.next.next
	st.size--
	return tmp.val
}

func (st *stack) isEmpty() bool {
	return st.size == 0
}
